﻿Imports WSEntidades
Imports Utilerias
Imports WSDatos

Public Class UsuariosBL

    Private Enum recuperarPor
        Usuario
        Correo
    End Enum

    Public Function Login(ByVal Rfc As String, ByVal Usuario As String, ByVal Password As String, _
                          ByRef token As String,
                          ByRef razonSocial As String, ByRef esquemaFacturacion As Enumeraciones.esquemaFacturacion,
                          ByRef nombreUsuario As String,
                          ByRef detResp As DetalleRespuesta) As Boolean
        Dim cuentaBL As CuentasBL = New CuentasBL()
        Dim userDAL As UsuarioDAL = New UsuarioDAL("")
        Dim strCadConexBDCliente As String = ""
        Dim boolChngPwd As Boolean = False
        Dim boolUserBloq As Boolean = False
        Dim dtCambioPwd As DateTime
        token = ""
        razonSocial = ""
        esquemaFacturacion = Enumeraciones.esquemaFacturacion.Indefinido
        nombreUsuario = ""
        Try
            If (EsValidoParaLogin(Rfc, Usuario, Password, detResp.Mensajes)) Then
                strCadConexBDCliente = cuentaBL.GenerarCadenaConexionClienteActivo(Rfc, detResp.Mensajes)
                If (strCadConexBDCliente = "") Then
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Catalogo_RegistroInexistenteOInactivo,
                                             "Cuenta inexistente o inactiva" & vbCrLf & detResp.Mensajes)
                    Return False
                End If
                userDAL = New UsuarioDAL(strCadConexBDCliente)
                If (userDAL.autenticarUsuario(Usuario, Password, boolChngPwd, boolUserBloq, dtCambioPwd, razonSocial, esquemaFacturacion, nombreUsuario)) Then
                    If (boolChngPwd Or ((DateTime.Now - dtCambioPwd).Days >= 30)) Then
                        detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Usuario_DebeCambiarContraseña,
                                                 "La contraseña debe ser cambiada antes de iniciar la sesión" & vbCrLf & detResp.Mensajes)
                    Else
                        detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ProcesamientoOK,
                                                 "Acceso autorizado" & vbCrLf & detResp.Mensajes)
                    End If
                    token = RijndaelSimple.encriptaDefault(strCadConexBDCliente)
                    Return True
                Else
                    If (boolUserBloq) Then
                        detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Usuario_CuentaBloqueadaPorSeguridad,
                                                 "El Usuario ha sido bloqueado por intentos fallidos de ingreso" & vbCrLf & detResp.Mensajes)
                    Else
                        detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Usuario_UsuarioOContraseñaIncorrectos,
                                                 "Usuario o contraseña incorrectos" & vbCrLf & detResp.Mensajes)
                    End If
                    Return False
                End If
            Else
                detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ValoresInvalidos,
                                     "Datos invalidos o incompletos para ingresar al sistema: " & vbCrLf & detResp.Mensajes)
                Return False
            End If
        Catch ex As Exception
            Log.LogException(ex, "UsuariosBL.Login")
            detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ExcepcionEnOperacion,
                                     detResp.Mensajes & "Excepción al autenticar usuario: " & ex.Message)
            Return False
        Finally
            cuentaBL = Nothing
            userDAL = Nothing
            strCadConexBDCliente = Nothing
            boolChngPwd = Nothing
            boolUserBloq = Nothing
            dtCambioPwd = Nothing
        End Try
    End Function

    Private Function EsValidoParaLogin(ByRef Rfc As String, ByVal Usuario As String,
                                       ByVal Password As String, ByRef mensaje As String) As Boolean
        mensaje = ""
        Try
            If (String.IsNullOrWhiteSpace(Rfc)) Then
                mensaje &= "El RFC del Cliente es obligatorio" & vbCrLf
            Else
                Rfc = Rfc.Trim.ToUpper

                Select Case Rfc.Length
                    Case 12
                        If (Not (csValidaciones.esRFCValidoPersonaMoral(Rfc))) Then
                            mensaje &= String.Format("RFC <{0}> no válido para Persona Moral", Rfc) & vbCrLf
                        End If

                    Case 13
                        If (Not (csValidaciones.esRFCValidoPersonaFisica(Rfc))) Then
                            mensaje &= String.Format("RFC <{0}> no válido para Persona Física", Rfc) & vbCrLf
                        End If

                    Case Else
                        mensaje &= String.Format("Longitud de RFC no válida (<{0}>)", Rfc) & vbCrLf
                End Select
            End If

            If (String.IsNullOrWhiteSpace(Usuario)) Then
                mensaje &= "El Nombre de Usuario es obligatorio" & vbCrLf
            End If

            If (String.IsNullOrWhiteSpace(Password)) Then
                mensaje &= "La Contraseña es obligatoria" & vbCrLf
            End If

            Return (mensaje = "")
        Catch ex As Exception
            Log.LogException(ex, "UsuarioBL.EsValidoParaLogin")
            mensaje &= ex.Message
            Return False
        End Try
    End Function

    Private Function EsValidoParaRecuperarUsuarioOContraseña(ByRef Rfc As String, ByVal dato As String, ByVal tipoRecuperacion As recuperarPor,
                                       ByRef mensaje As String) As Boolean
        mensaje = ""
        Try
            If (String.IsNullOrWhiteSpace(Rfc)) Then
                mensaje &= "El RFC del Cliente es obligatorio" & vbCrLf
            Else
                Rfc = Rfc.Trim.ToUpper

                Select Case Rfc.Length
                    Case 12
                        If (Not (csValidaciones.esRFCValidoPersonaMoral(Rfc))) Then
                            mensaje &= String.Format("RFC <{0}> no válido para Persona Moral", Rfc) & vbCrLf
                        End If

                    Case 13
                        If (Not (csValidaciones.esRFCValidoPersonaFisica(Rfc))) Then
                            mensaje &= String.Format("RFC <{0}> no válido para Persona Física", Rfc) & vbCrLf
                        End If

                    Case Else
                        mensaje &= String.Format("Longitud de RFC no válida (<{0}>)", Rfc) & vbCrLf
                End Select
            End If

            If (String.IsNullOrWhiteSpace(dato)) Then
                Select Case tipoRecuperacion
                    Case recuperarPor.Usuario
                        mensaje &= "El Nombre de Usuario es obligatorio" & vbCrLf
                    Case recuperarPor.Correo
                        mensaje &= "El Correo del Usuario es obligatorio" & vbCrLf
                End Select
            Else
                If (tipoRecuperacion = recuperarPor.Correo) Then
                    If (Not (csValidaciones.esCorreoValido(dato))) Then
                        mensaje &= String.Format("Dirección de Correo Electrónico <{0}> no válido.{1}", dato, vbCrLf)
                    End If
                End If
            End If

            Return (mensaje = "")
        Catch ex As Exception
            Log.LogException(ex, "UsuarioBL.EsValidoParaRecuperarContraseña")
            mensaje &= ex.Message
            Return False
        End Try
    End Function

    Public Function RecuperarContraseña(ByVal RFC As String, ByVal usuario As String,
                                        ByRef detResp As DetalleRespuesta) As Boolean
        Dim cuentaBL As CuentasBL = New CuentasBL()
        Dim userDAL As UsuarioDAL = New UsuarioDAL("")
        Dim strCadConexCliente As String = ""
        Dim strContraseña As String = ""
        Dim strCorreoUsuario As String = ""
        Dim mailBL As EnviosDeCorreoBL = New EnviosDeCorreoBL()
        detResp.Mensajes = ""
        Try
            If (EsValidoParaRecuperarUsuarioOContraseña(RFC, usuario, recuperarPor.Usuario, detResp.Mensajes)) Then
                strCadConexCliente = cuentaBL.GenerarCadenaConexionClienteActivo(RFC, detResp.Mensajes)
                If (strCadConexCliente = "") Then
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Catalogo_RegistroInexistenteOInactivo,
                                             "Cuenta inexistente o inactiva" & vbCrLf & detResp.Mensajes)
                    Return False
                End If
                userDAL = New UsuarioDAL(strCadConexCliente)
                strContraseña = userDAL.modificaContraseña(usuario, strCorreoUsuario)
                If (strContraseña = "") Then
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Catalogo_RegistroInexistenteOInactivo,
                                             "No se encontró registro del Usuario, está inactivo o pertenece a un perfil inactivo" & vbCrLf & detResp.Mensajes)
                    Return False
                End If
                'Se cambio la contraseña, enviarla por correo al usuario
                If (strCorreoUsuario = "") Then
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Usuario_SinCorreoElectronico,
                                             "El registro del usuario no contiene Correo Electrónico para enviar notificación de cambio de contraseña" & vbCrLf & detResp.Mensajes)
                    Return True
                Else
                    mailBL.enviaMailCambioContraseña(RFC, usuario, strContraseña, strCorreoUsuario)
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ProcesamientoOK,
                                            "La Contraseña fue cambiada y se ha enviado notificación al correo <" & strCorreoUsuario & ">" & vbCrLf & detResp.Mensajes)
                    Return True
                End If
            Else
                detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ValoresInvalidos,
                                         "Datos invalidos o incompletos para proceso de recuperación de contraseña: " & vbCrLf & detResp.Mensajes)
                Return False
            End If
        Catch ex As Exception
            Log.LogException(ex, "UsuariosBL.RecuperarContraseña")
            detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ExcepcionEnOperacion,
                                     detResp.Mensajes & "Excepción al cambiar contraseña del usuario <" & usuario & ">: " & ex.Message)
            Return False
        Finally
            cuentaBL = Nothing
            userDAL = Nothing
            strCadConexCliente = Nothing
            strContraseña = Nothing
            strCorreoUsuario = Nothing
            mailBL = Nothing
        End Try
    End Function

    Public Function cambiarContraseña(ByVal tokenConexion As String, ByVal usuario As String, ByVal pwdActual As String,
                                    ByVal pwdNuevo As String, ByRef detResp As DetalleRespuesta) As Boolean
        Dim userDAL As UsuarioDAL = New UsuarioDAL("")
        detResp.Mensajes = ""
        Try
            tokenConexion = RijndaelSimple.desencriptaDefault(tokenConexion)
            If (esValidoParaCambiarPwd(usuario, pwdActual, pwdNuevo, detResp.Mensajes)) Then
                userDAL = New UsuarioDAL(tokenConexion)
                'Verificar contraseña nueva no esta en historicos
                If (userDAL.esContraseñaHistorica(usuario, pwdNuevo)) Then
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ValoresInvalidos,
                                             "Datos inválidos para cambiar contraseña:  La Contraseña Nueva no debe ser alguna de las ultimas 3 utilizadas." & vbCrLf & detResp.Mensajes)
                    Return False
                End If
                If (userDAL.modificaContraseña(usuario, pwdActual, pwdNuevo)) Then
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ProcesamientoOK, "La Contraseña fue cambiada correctamente.")
                    Return True
                Else
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Catalogo_NoFueActualizado,
                                             "La Contraseña no pudo ser cambiada:  Verifique que el Usuario sea correcto, esté Activo y su Contraseña Actual sea correcta." & vbCrLf & detResp.Mensajes)
                    Return False
                End If
            Else
                detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ValoresInvalidos,
                                         "Datos inválidos para cambiar contraseña: " & vbCrLf & detResp.Mensajes)
                Return False
            End If
        Catch ex As Exception
            Log.LogException(ex, "UsuariosBL.cambiarContraseña")
            detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ExcepcionEnOperacion,
                                        detResp.Mensajes & "Excepción al cambiar contraseña del usuario <" & usuario & ">: " & ex.Message)
            Return False
        Finally
            userDAL = Nothing
        End Try
    End Function

    Private Function esValidoParaCambiarPwd(ByVal usuario As String, ByVal pwdActual As String, ByVal pwdNuevo As String,
                                            ByRef msg As String) As Boolean
        msg = ""
        Try
            If (String.IsNullOrWhiteSpace(usuario)) Then
                msg &= "El campo Usuario es obligatorio." & vbCrLf
            End If

            If (String.IsNullOrWhiteSpace(pwdActual)) Then
                msg &= "El campo Contraseña Actual es obligatorio." & vbCrLf
            End If

            If (String.IsNullOrWhiteSpace(pwdNuevo)) Then
                msg &= "El campo Contraseña Nueva es obligatorio." & vbCrLf
            Else
                If Not (csValidaciones.esContraseñaSegura(pwdNuevo)) Then
                    msg &= "El campo Contraseña Nueva no cumple con las reglas de una contraseña segura." & vbCrLf
                Else
                    'Es contraseña segura, verificar si no es igual a la actual
                    If (pwdNuevo = pwdActual) Then
                        msg &= "La Contraseña Nueva no puede ser la misma que la Contraseña Actual." & vbCrLf
                    End If
                End If
            End If

            Return (msg = "")
        Catch ex As Exception
            Log.LogException(ex, "UsuarioBL.esValidoParaCambiarPwd")
            msg &= ex.Message
            Return False
        End Try
    End Function

    Public Function RecuperarUsuario(ByVal RFC As String, ByVal correo As String, ByRef detResp As DetalleRespuesta) As Boolean
        Dim cuentaBL As CuentasBL = New CuentasBL()
        Dim userDAL As UsuarioDAL = New UsuarioDAL("")
        Dim strCadConexCliente As String = ""
        Dim strContraseña As String = ""
        Dim strNombreUsuario As String = ""
        Dim mailBL As EnviosDeCorreoBL = New EnviosDeCorreoBL()
        detResp.Mensajes = ""
        Try
            If (EsValidoParaRecuperarUsuarioOContraseña(RFC, correo, recuperarPor.Correo, detResp.Mensajes)) Then
                strCadConexCliente = cuentaBL.GenerarCadenaConexionClienteActivo(RFC, detResp.Mensajes)
                If (strCadConexCliente = "") Then
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Catalogo_RegistroInexistenteOInactivo,
                                             "Cuenta inexistente o inactiva" & vbCrLf & detResp.Mensajes)
                    Return False
                End If
                userDAL = New UsuarioDAL(strCadConexCliente)
                strContraseña = userDAL.modificaContraseñaPorCorreo(correo, strNombreUsuario)
                If (strContraseña = "") Then
                    detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.Catalogo_RegistroInexistenteOInactivo,
                                             "No se encontró registro del Correo, está inactivo o pertenece a un perfil inactivo" & vbCrLf & detResp.Mensajes)
                    Return False
                End If
                'Se cambio la contraseña, enviarla por correo al usuario
                mailBL.enviaMailCambioContraseña(RFC, strNombreUsuario, strContraseña, correo)
                detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ProcesamientoOK,
                                        "El Nombre de Usuario fue recuperado y la Contraseña fue cambiada.  Se han enviado los datos al correo <" & correo & ">" & vbCrLf & detResp.Mensajes)
                Return True
                
            Else
                detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ValoresInvalidos,
                                         "Datos invalidos o incompletos para proceso de Recuperación de Usuario: " & vbCrLf & detResp.Mensajes)
                Return False
            End If
        Catch ex As Exception
            Log.LogException(ex, "UsuariosBL.RecuperarUsuario")
            detResp.estableceValores(DetalleRespuesta.CodigoRespuesta.ExcepcionEnOperacion,
                                     detResp.Mensajes & "Excepción al Recuperar Usuario por medio del Correo <" & correo & ">: " & ex.Message)
            Return False
        Finally
            cuentaBL = Nothing
            userDAL = Nothing
            strCadConexCliente = Nothing
            strContraseña = Nothing
            strNombreUsuario = Nothing
            mailBL = Nothing
        End Try
    End Function

End Class
